﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlExtractor.Output;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Collections;

namespace HtmlExtractor.XPathOutput
{
    /// <summary>
    /// 处理一个key对应的inputdata
    /// </summary>
    public abstract class XmlDocOutputPathProcessor : IOutputPathProcessor<XDocument>
    {
        public XmlDocOutputPathProcessor()
        { }
        public XmlDocOutputPathProcessor(IGrouping<List<string>, IPageItem> inputData)
        {
            InputData = inputData;
        }

        private XDocument template;
        internal XDocument Template
        { get { return template; } }
        internal XPathNavigator Navigator
        {
            get { return Template.CreateNavigator(); }
        }
        /// <summary>
        /// 默认命名空间加empty，xlinqbug?
        /// </summary>
        protected XmlNamespaceManager NameSpace
        {
            get
            {
                XmlNamespaceManager nameSpaceMan = new XmlNamespaceManager(template.CreateReader().NameTable);
                foreach (XAttribute attr in template.Root.Attributes())
                {
                    if (attr.IsNamespaceDeclaration)
                    {
                        if (string.IsNullOrEmpty(attr.Name.NamespaceName))
                        {
                            nameSpaceMan.AddNamespace("empty", attr.Value);
                        }
                        else
                        {
                            nameSpaceMan.AddNamespace(attr.Name.LocalName, attr.Value);
                        }
                    }
                
                }
                return nameSpaceMan;
            }
        }
        public IGrouping<List<string>, IPageItem> InputData
        { get; set; }

        #region IOutputPathProcessor<XElement> Members

        public virtual bool GetResult(ref XDocument outputData)
        {
           template = outputData;
            return false;
        }
        protected void EvaluateXPath(ref XDocument xdoc, string outputPath, string s)
        {
            s = s.FormatXml();
            XPathOutputPathParser parser = new XPathOutputPathParser(outputPath);
            string xPath=parser.ElementSegment;
            string selector=parser.AttributeSegment;
            IEnumerable<XElement> elements = xdoc.XPathSelectElements(xPath,NameSpace);
            foreach (XElement element in elements)
            {
                if (!string.IsNullOrEmpty(selector))
                {
                    IEnumerable result = element.XPathEvaluate(selector.Trim()) as IEnumerable;
                    if (result != null)
                    {
                        XObject value = result.Cast<XObject>().FirstOrDefault();
                        if (value is XElement)
                            ((XElement)value).Value = s;
                        else if (value is XText || value is XCData)
                            ((XText)value).Value = s;
                        else if (value is XAttribute)
                            ((XAttribute)value).Value = s;
                        else
                            throw new NotSupportedException();
                    }
                }
                else
                {
                    element.Value = s;
                }
            }
        }
        protected void EvaluateXPath(XElement xdoc, string outputPath, string s)
        {
            xdoc.ToString();
            XPathOutputPathParser parser = new XPathOutputPathParser(outputPath);
            string xPath = parser.ElementSegment;
            string selector = parser.AttributeSegment;
            IEnumerable<XElement> elements = xdoc.XPathSelectElements(xPath,NameSpace);
            foreach (XElement element in elements)
            {
                if (!string.IsNullOrEmpty(selector))
                {
                    IEnumerable result = element.XPathEvaluate(selector.Trim()) as IEnumerable;
                    if (result != null)
                    {
                        XObject value = result.Cast<XObject>().FirstOrDefault();
                        if (value is XElement)
                            ((XElement)value).Value = s;
                        else if (value is XText || value is XCData)
                            ((XText)value).Value = s;
                        else if (value is XAttribute)
                            ((XAttribute)value).Value = s;
                        else
                            throw new NotSupportedException();
                    }
                }
                element.Value = s;
            }
        }
        #endregion
    }
}
